/**
 * @author Nicolas Latorre
 */
package sa4.template

import javax.servlet.http._
import scala.xml._
import java.io.File
import javax.imageio.ImageIO
import scala.io.Codec

class Template {

  /**
   * Function that will loads a file containing an html page.
   * @param filePath	a String that represent the name of the file.
   * @return			a NodeSeq that contain the html page.
   */
  def loadPage(filePath: String): NodeSeq = {
    val basePage = scala.io.Source.fromFile(filePath)(Codec.ISO8859).toArray.mkString
    XML.loadString(basePage)
  }

  /**
   * Function that will load a file from the file system.
   * @param filePath	a String that contain the name of the file.
   * @return			a String that contain all the file.
   */
  def loadFile(filePath: String) = {
    val basePage = scala.io.Source.fromFile(filePath)(Codec.ISO8859).toArray.mkString
    basePage
  }

  /**
   * Function that will load an image from the file system.
   * @param filePath	a String that contain the name of the image that we want to load.
   * @return img		a BufferedImage that represent the image loaded.
   */
  def loadImage(filePath: String) = {
    val img = ImageIO.read(new File(filePath))
    img
  }

  /**
   * Function that loads a template to be displayed
   * @param filePath	a String that contain the file containing the template to be used.
   * @return			a xml.Elem that contain the default template.
   */
  def getDefaultTemplate(filePath: String) = {
    val surround = scala.io.Source.fromFile(filePath)(Codec.ISO8859).toArray.mkString
    XML.loadString(surround)
  }

  /**
   * Loads the default template to be used, and display it.
   * @param	filePath	a String that contain the filePath.
   * @return			a NodeSeq that contain the processed template.
   */
  def setUpTemplate(fileName: String) = {
    val template = getDefaultTemplate(fileName)
    val ns = processTemplate(template)
    ns
  }

  /**
   * Function that process template and replace the content of the target page with the corresponding template.
   * @param template	a NodeSeq that contain the template.
   * @return			a NodeSeq with the content replaced with the template.
   */
  def processTemplate(template: NodeSeq): NodeSeq = {
    import scala.xml.transform._
    import scala.xml.Null // hide scala.Null
    class ProcessWrapper(ns: NodeSeq, location: String) extends RewriteRule {
      override def transform(n: Node): Seq[Node] = n match {
        case elem: Elem if elem.label == "div" && (elem.attribute("id")).toString() == "Some(" + location + "/)" =>
          ns
        case n => n
      }
    }

    object ProcessSurround extends RewriteRule {
      override def transform(n: Node): Seq[Node] = n match {
        case elem: Elem if elem.label == "surround" =>
          val wrapperName = (elem \\ "@with").text
          val where = (elem \\ "@at").text

          val wrapperNode = loadPage(wrapperName)

          val wrappedNode = elem.child
          wrapperNode.map(ns => new RuleTransformer(new ProcessWrapper(wrappedNode, where))(ns))
        case n => n
      }
    }
    template.map(ns => new RuleTransformer(ProcessSurround)(ns))
  }
}